package com.fj.netty.chat.protocol;

import com.fj.netty.chat.message.Message;
import com.fj.netty.chat.serializer.SerializeConfig;
import com.fj.netty.chat.serializer.Serializer;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageCodec;
import lombok.extern.slf4j.Slf4j;

import java.util.List;

/**
 * 消息编解码器
 * @author fj
 * @date 2024/1/11 14:25
 */
@Slf4j
public class MessageCodec extends ByteToMessageCodec<Message> {

    public static final byte[] MAGIC = {1, 2, 3, 4};

    @Override
    protected void encode(ChannelHandlerContext ctx, Message msg, ByteBuf out) throws Exception {
//        log.debug("encode开始");
        //4字节魔数
        out.writeBytes(MAGIC);
        //1字节版本号
        out.writeByte(1);
        //1字节序列化方式 0JAVA 1JSON
        Serializer.Algorithm algorithm = SerializeConfig.getSerializer();
//        log.debug("序列化方式为:{}",algorithm);
        out.writeByte(algorithm.ordinal());
        //1字节消息类型
        out.writeByte(msg.getMessageType());
        //4字节序列号
        out.writeInt(0);
        //1字节补位
        out.writeByte(0xFF);
        //4字节长度
        byte[] bytes = algorithm.serialize(msg);
        out.writeInt(bytes.length);
        //其它自己为内容
        out.writeBytes(bytes);
//        log.debug("encode结束");
    }

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        int magic = in.readInt();
        byte version = in.readByte();
        byte serializeAlgorithm = in.readByte();
        byte messageType = in.readByte();
        int sequenceId = in.readInt();
        //跳过补位字节
        in.readByte();
        int length = in.readInt();
        byte[] bytes = new byte[length];
        in.readBytes(bytes);
        Serializer.Algorithm algorithm = Serializer.Algorithm.values()[serializeAlgorithm];
        Class<? extends Message> messageClass = Message.getMessageClass(messageType);
        Object message = algorithm.deserialize(bytes,messageClass);
        log.debug("decode -> {}",message);
        out.add(message);
    }
}
